package com.credithc.signature.manager.service;

import com.credithc.signature.common.mapper.CallChannelHourMapper;
import com.credithc.signature.common.mapper.CallHourMapper;
import com.credithc.signature.common.mapper.CallStatisticsMapper;
import com.credithc.signature.common.po.CallChannelHour;
import com.credithc.signature.common.po.CallStatistics;
import com.credithc.signature.common.service.SignatureLogService;
import com.credithc.signature.common.utils.TimeUtil;
import com.credithc.signature.common.vo.manager.ChartVo;
import com.credithc.signature.common.vo.manager.SerieVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 描 述: <br/>
 * 作 者: Jingbo Hu<br/>
 * 创 建：2019年08⽉28⽇<br/>
 * 版 本：v1.0.0<br>
 * <p>
 * 历 史: (版本) 作者 时间 注释 <br/>
 */
@Slf4j
@Service
public class StatisticsService {

    private static final SimpleDateFormat SIMPLEDATEFORMAT = new SimpleDateFormat("yyyyMMdd");
    private static Map<String, SerieVo> serieVoMap = new HashMap<>(16);
    private static String SUCCESSCLASSFY = "成功订单";
    private static String FAILCLASSFY = "失败订单";

    @Autowired
    private CallStatisticsMapper callStatisticsMapper;

    @Autowired
    private CallHourMapper callHourMapper;

    @Autowired
    private CallChannelHourMapper callChannelHourMapper;

    @Autowired
    private TemplateMService templateService;

    @Autowired
    SignatureLogService requestLogService;

    /**
     * 按天统计总量
     *
     * @param start
     * @param stop
     * @param channelNos
     * @return
     */
    public ChartVo dayStatistics(Date start, Date stop, List<String> channelNos) {

        Example example = new Example(CallStatistics.class);
        Example.Criteria criteria = example.createCriteria();
        String startTime = null;
        String stopTime = null;
        if (start.equals(stop)) {
            startTime = SIMPLEDATEFORMAT.format(TimeUtil.prevDay(start, 7));
            stopTime = SIMPLEDATEFORMAT.format(TimeUtil.nextDay(stop, 1));
        } else {
            startTime = SIMPLEDATEFORMAT.format(start);
            stopTime = SIMPLEDATEFORMAT.format(TimeUtil.nextDay(stop, 1));
        }
        criteria.andBetween("timeId", startTime, stopTime);
        criteria.andIn("channelNo", channelNos);
        List<CallStatistics> statisticsList = callStatisticsMapper.selectByExample(example);

        //封装参数
        List<String> dates = buildDate(start, stop);
        List<String> classifys = buildClassify();
        List<SerieVo> series = bulidSeries(classifys);
        buildDiffData(dates, statisticsList);
        buildData(dates, statisticsList);

        ChartVo chartVo = new ChartVo();
        chartVo.setClassify(classifys);
        chartVo.setDates(dates);
        chartVo.setSeries(series);
        return chartVo;
    }

    /**
     * 封装空白数据
     *
     * @param dates
     * @param statisticsList
     */
    private void buildDiffData(List<String> dates, List<CallStatistics> statisticsList) {
        //封装callStatistics数据
        List<CallStatistics> newCallList = new ArrayList<>();
        Set<String> timeIds = statisticsList.stream().map(CallStatistics::getTimeId).collect(Collectors.toSet());
        for (String date : dates) {
            if (!timeIds.contains(date)) {
                CallStatistics cs = new CallStatistics();
                cs.setNum(0);
                cs.setStatus(1);
                cs.setTimeId(date);
                cs.setChannelNo(null);
                CallStatistics cs1 = new CallStatistics();
                cs1.setNum(0);
                cs1.setStatus(0);
                cs1.setTimeId(date);
                cs.setChannelNo(null);
                newCallList.add(cs);
                newCallList.add(cs1);
            }
        }
        statisticsList.addAll(newCallList);
    }

    /**
     * 封装展示数据
     *
     * @param dates
     * @param callStatistics
     */
    private void buildData(List<String> dates, List<CallStatistics> callStatistics) {
        for (String date : dates) {
            for (CallStatistics cs : callStatistics) {
                if (date.equals(cs.getTimeId())) {
                    SerieVo serieVo = serieVoMap.get(cs.getStatus() == 0 ? "成功订单" : "失败订单");
                    List<Integer> data = serieVo.getData();
                    data.add(cs.getNum());
                }
            }
        }
    }

    /**
     * 封装Serievos
     *
     * @param classifies
     * @return
     */
    private List<SerieVo> bulidSeries(List<String> classifies) {
        List<SerieVo> series = new ArrayList<>();
        classifies.forEach(c -> {
            SerieVo serieVo = new SerieVo();
            List<Integer> datas = new ArrayList<>();
            serieVo.setData(datas);
            serieVo.setName(c);
            serieVo.setType("line");
            serieVo.setSmooth(true);
            serieVoMap.put(c, serieVo);
            series.add(serieVo);

        });
        return series;
    }

    /**
     * 封装classFy
     *
     * @return
     */
    private List<String> buildClassify() {
        List<String> list = new ArrayList<>();
        list.add(SUCCESSCLASSFY);
        list.add(FAILCLASSFY);
        return list;
    }

    /**
     * 封装时间轴
     *
     * @param
     * @return
     */
    private List<String> buildDate(Date start, Date stop) {
        List<String> dates = new ArrayList<>();
        Long days = null;
        if (start.equals(stop)) {
            start = TimeUtil.prevDay(start, 7);
            days = TimeUtil.betWeenDays(start, stop);
        } else {
            days = TimeUtil.betWeenDays(start, stop);
        }
        dates.add(SIMPLEDATEFORMAT.format(start));
        for (int i = 1; i < days; i++) {
            Date date = TimeUtil.nextDay(start, i);
            dates.add(SIMPLEDATEFORMAT.format(date));
        }
        return dates;
    }

    public ChartVo pvStatistics(List<String> channelNos) {
        Example example = new Example(CallChannelHour.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("channelNo", channelNos);
        bulidExample(null, criteria);
        List<CallChannelHour> callChannelHours = callChannelHourMapper.selectByExample(example);
        List<String> dates = new ArrayList<>();
        SerieVo serieVo = new SerieVo();
        serieVo.setName("调用PV");
        serieVo.setData(new ArrayList<>());
        serieVo.setType("line");
        List<SerieVo> serieVos = new ArrayList<>();
        serieVos.add(serieVo);
        for (CallChannelHour ch : callChannelHours) {
            dates.add(getViewTime(ch.getTimeId()));
            List<Integer> data = serieVo.getData();
            data.add(ch.getNum());
        }
        List<String> classify = new ArrayList<>();
        classify.add(serieVo.getName());
        ChartVo chartVo = new ChartVo();
        chartVo.setDates(dates);
        chartVo.setClassify(classify);
        chartVo.setSeries(serieVos);
        return chartVo;

    }


    private void bulidExample(Date date, Example.Criteria criteria) {
        String pattern = "yyyyMMddHHmm";
        String end = TimeUtil.nowTime(pattern);
        String start = TimeUtil.prevTime(13, pattern);
        criteria.andBetween("timeId", start, end);
    }

    private String getViewTime(String timeId) {
        SimpleDateFormat timeIdFormat = new SimpleDateFormat("yyyyMMddHH");
        SimpleDateFormat viewFormat = new SimpleDateFormat("MM/dd HH:mm");
        String viewTime = null;
        try {
            Date parse = timeIdFormat.parse(timeId);
            viewTime = viewFormat.format(parse);
        } catch (ParseException e) {
            log.info("时间转换异常 时间id:{}", timeId, e);
        }
        return viewTime;
    }

    public ChartVo systemStatistics(List<String> channelNos) {
        Example example = new Example(CallChannelHour.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andIn("channelNo", channelNos);
        bulidExample(null, criteria);
        List<CallChannelHour> callChannelHours = null;
        try {
            callChannelHours = callChannelHourMapper.selectByExample(example);
        } catch (Exception e) {
            log.error("统计类StatisticsService[systemStatistics]方法发生异常", e);
        }
        List<String> dates = new ArrayList<>();
        List<String> classify = new ArrayList<>();
        Set<String> dateSet = new HashSet<>();
        Set<String> classifySet = new HashSet<>();
        for (CallChannelHour cch : callChannelHours) {
            String timeId = cch.getTimeId();
            if (dateSet.add(timeId)) {
                String viewTime = getViewTime(timeId);

                dates.add(viewTime);
            }
            if (classifySet.add(cch.getChannelName())) {
                classify.add(cch.getChannelName());
            }
        }

        List<SerieVo> serieVos = new ArrayList<>();
        Map<String, SerieVo> map = new HashMap<>(16);
        bulidSerie(classify, serieVos, map);
        for (CallChannelHour cch : callChannelHours) {
            SerieVo serieVo = map.get(cch.getChannelName());
            List<Integer> data = serieVo.getData();
            data.add(cch.getNum());
        }
        ChartVo chartVo = new ChartVo();
        chartVo.setDates(dates);
        chartVo.setClassify(classify);
        chartVo.setSeries(serieVos);
        return chartVo;
    }

    private void bulidSerie(List<String> list, List<SerieVo> series, Map<String, SerieVo> serieVoMap) {
        for (String s : list) {
            SerieVo serieVo = new SerieVo();
            List<Integer> datas = new ArrayList<>();
            serieVo.setData(datas);
            serieVo.setName(s);
            serieVo.setType("line");
            serieVo.setSmooth(true);
            serieVoMap.put(s, serieVo);
            series.add(serieVo);
        }
    }
}
